﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using HA.ModFlow.Domain.DomainLayer;

namespace HA.Data
{

    /// <summary>
    /// 这里表示一些源汇项以及属性，名字BC至今不知道是啥意思，
    /// </summary>
    [Serializable]
    public abstract class BCType
    {


        public BCType()
        {
            //this._nPeriods = nPeriods;
        }


      protected  MAPSCType _scType;


        /// <summary>
        /// 用于表示对应的枚举类型
        /// </summary>
        public MAPSCType ScType
        {
            get { return _scType; }
            set { _scType = value; }
        }


        protected bool _isPtType;


        /// <summary>
        /// 表示是否可以被赋予点数据
        /// </summary>
        public bool IsPtType
        {
            get { return _isPtType; }
           
        }

        protected bool _isLnType;

        public bool IsLnType
        {
            get { return _isLnType; }
            set { _isLnType = value; }
        }

        protected bool _isPyType;

        public bool IsPyType
        {
            get { return _isPyType; }
            set { _isPyType = value; }
        }


        //int _nPeriods=1;

        //public int NPeriods
        //{
        //    get { return _nPeriods; }
        //    set {

        //        if (this._nPeriods!=value)
        //        {
        //            _nPeriods = value;

        //            this.OnNPeriodsChanged();
        //        }
               
            
            
        //    }
        //}

        //public virtual void OnNPeriodsChanged()
        //{ 

        //}

        public abstract void MapToModflow(List<double> stressPeriods, List<ValueResult > ijkList, ModFlowData mf,FeatureObject owner);
        //public abstract void MapToModflow(List<int[]> ijkList, ModFlowData mf);


        //public virtual void MapToModflow(FeatureObject  owner,ModFlowData mf)
        //{




 
        //}

        protected void assistMapToModFlow(List<double> stressPeriods, List<double> gennerInner, BCDateDataCollection datas)
        {
            if (datas.IsDataConst)
            {
                for (int i = 0; i < stressPeriods.Count; i++)
                {
                    gennerInner[i] = datas.ConstData;
                }

                return;
            }

            List<BCDateData> dataValues = datas.BCDatas;
            
            int j = 0;
            //开始按应力期循环
            for (int i = 0; i < stressPeriods.Count; i++)
            {
                //如果设置的时间段未遍历完毕且在应力期内 
                if (j < dataValues.Count)
                {
                    //如果前一个应力期刚好将时间段用完
                    if (i >= 1 && j == dataValues.Count - 1 && stressPeriods[i - 1] >= dataValues[j].EndTime)
                    {
                        break;
                    }
                    //如果该应力期在同一个时间段内
                    if (stressPeriods[i] <= dataValues[j].EndTime)
                    {
                        gennerInner[i] = dataValues[j].Value;
                        if (stressPeriods[i] == dataValues[j].EndTime)
                            j++;
                    }
                    else //该应力期不在同一个时间段内
                    {
                        int start = j;

                        if (dataValues[dataValues.Count - 1].EndTime >= stressPeriods[i])
                        {
                            while (dataValues[j].EndTime < stressPeriods[i])
                            {
                                j++;
                            }
                        }
                        else
                        {
                            j = dataValues.Count - 1;
                        }
                        double sumValue = 0;

                        if (j >= start)
                        {
                            if (j == start)//过滤掉在同一应力期的无效数据
                            {
                                if (i >= 1)
                                {
                                    if (stressPeriods[i - 1] < dataValues[j].Value)
                                    {
                                        gennerInner[i] = (dataValues[j].EndTime - stressPeriods[i - 1]) * dataValues[j].Value / (stressPeriods[i] - stressPeriods[i - 1]);
                                    }
                                }
                                else
                                {
                                    gennerInner[i] = dataValues[j].EndTime  * dataValues[j].Value / stressPeriods[i];
                                }
                                break;
                            }

                            if (i > 0)
                                sumValue = (dataValues[start].EndTime - stressPeriods[i - 1]) * dataValues[start].Value;
                            else
                                sumValue = (dataValues[start].EndTime - dataValues[start].StartTime + 1) * dataValues[start].Value;
                            for (int t = start + 1; t < j; t++)
                            {
                                sumValue += (dataValues[t].EndTime - dataValues[t].StartTime + 1) * dataValues[t].Value;
                            }
                            if (j < dataValues.Count - 1)
                                sumValue += (stressPeriods[i] - dataValues[j].StartTime + 1) * dataValues[j].Value;
                            else
                            {

                                sumValue += ((dataValues[j].EndTime > stressPeriods[i] ? stressPeriods[i] : dataValues[j].EndTime) - dataValues[j].StartTime + 1) * dataValues[j].Value;
                            }
                            sumValue /= (i == 0 ? (stressPeriods[i]) : (stressPeriods[i] - stressPeriods[i - 1]));
                            gennerInner[i] = sumValue;
                        }
                    }
                }//end if 设置的时间段未遍历完毕且在应力期内 
                else
                {
                    //终止循环 即剩余应力期数据为默认值0
                    break;
                }
            }
        }

    }
}
